package org.abc.fund.service.funds;

import org.abc.fund.dto.FundPortfolioWithFundsDTO;
import org.abc.fund.dto.FundPortfolioWithFundsDTO.FundDTO;
import org.abc.fund.entity.funds.FundBasicInfo;
import org.abc.fund.entity.funds.FundPortfolio;
import org.abc.fund.entity.funds.FundPortfolioItem;
import org.abc.fund.repository.funds.FundBasicInfoRepository;
import org.abc.fund.repository.funds.FundPortfolioItemRepository;
import org.abc.fund.repository.funds.FundPortfolioRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import static org.abc.fund.controller.funds.FundPortfolioController.SavePortfolioRequest;

@Service
public class FundPortfolioService {

  private static final Logger logger = Logger.getLogger(FundPortfolioService.class.getName());

  private final FundPortfolioRepository portfolioRepository;

  private final FundPortfolioItemRepository itemRepository;

  private final FundBasicInfoRepository fundBasicInfoRepository;

  public FundPortfolioService(
      FundPortfolioRepository portfolioRepository,
      FundPortfolioItemRepository itemRepository,
      FundBasicInfoRepository fundBasicInfoRepository) {
    this.portfolioRepository = portfolioRepository;
    this.itemRepository = itemRepository;
    this.fundBasicInfoRepository = fundBasicInfoRepository;
  }

  /** 分页查询：我的组合 + 每个组合包含的基金信息 */
  public Page<FundPortfolioWithFundsDTO> getPortfoliosWithFunds(Long userId, int page, int size) {
    Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));

    FundPortfolio probe = new FundPortfolio();
    probe.setUserId(userId);

    Page<FundPortfolio> portfolioPage = portfolioRepository.findAll(Example.of(probe), pageable);

    List<Long> portfolioIds =
        portfolioPage.getContent().stream().map(FundPortfolio::getId).toList();

    // 查询所有组合下的基金项
    List<FundPortfolioItem> allItems = itemRepository.findByPortfolioIdIn(portfolioIds);

    // 查出所有基金详情
    Set<String> fundCodes =
        allItems.stream().map(FundPortfolioItem::getFundCode).collect(Collectors.toSet());

    Map<String, FundBasicInfo> fundMap =
        fundBasicInfoRepository.findByCodeIn(new ArrayList<>(fundCodes)).stream()
            .collect(Collectors.toMap(FundBasicInfo::getCode, fund -> fund));

    // 组合 ID → 其包含的基金列表
    Map<Long, List<FundDTO>> portfolioFundMap = new HashMap<>();
    for (FundPortfolioItem item : allItems) {
      FundBasicInfo fund = fundMap.get(item.getFundCode());
      if (fund != null) {
        FundDTO dto = new FundDTO();
        dto.setCode(fund.getCode());
        dto.setName(fund.getName());
        dto.setType(fund.getType());
        dto.setCompanyName(fund.getCompany() != null ? fund.getCompany().getName() : null);
        dto.setLatestNav(fund.getLatestNav());
        dto.setLatestNavDate(
            fund.getLatestNavDate() != null ? fund.getLatestNavDate().toString() : null);

        portfolioFundMap.computeIfAbsent(item.getPortfolioId(), k -> new ArrayList<>()).add(dto);
      }
    }

    // 构建最终 DTO 列表
    List<FundPortfolioWithFundsDTO> dtoList =
        portfolioPage.getContent().stream()
            .map(
                p -> {
                  FundPortfolioWithFundsDTO dto = new FundPortfolioWithFundsDTO();
                  dto.setId(p.getId());
                  dto.setUserId(p.getUserId());
                  dto.setName(p.getName());
                  dto.setDescription(p.getDescription());
                  dto.setCreateTime(p.getCreateTime());
                  dto.setFunds(portfolioFundMap.getOrDefault(p.getId(), Collections.emptyList()));
                  return dto;
                })
            .toList();

    return new PageImpl<>(dtoList, pageable, portfolioPage.getTotalElements());
  }

  /** 查询某个用户的所有组合（不分页） */
  public List<FundPortfolio> getPortfoliosByUserId(Long userId) {
    return portfolioRepository.findByUserId(userId);
  }

  /** 创建组合（备用） */
  public FundPortfolio createPortfolio(FundPortfolio portfolio) {
    portfolio.setCreateTime(LocalDateTime.now());
    return portfolioRepository.save(portfolio);
  }

  /** 创建组合并添加基金项 */
  public void savePortfolioWithFunds(SavePortfolioRequest request) {
    FundPortfolio portfolio = new FundPortfolio();
    portfolio.setUserId(request.getUserId());
    portfolio.setName(request.getName());
    portfolio.setDescription(request.getDescription());
    portfolio.setCreateTime(LocalDateTime.now());

    FundPortfolio saved = portfolioRepository.save(portfolio);

    List<FundPortfolioItem> items =
        request.getFundCodes().stream()
            .distinct()
            .map(
                code -> {
                  FundPortfolioItem item = new FundPortfolioItem();
                  item.setPortfolioId(saved.getId());
                  item.setFundCode(code);
                  return item;
                })
            .toList();

    itemRepository.saveAll(items);
    logger.info("已保存组合：" + saved.getName() + "，共添加基金 " + items.size() + " 只");
  }

  /** 删除组合及其基金项（事务处理） */
  @Transactional
  public void deletePortfolio(Long id) {
    logger.info("尝试删除组合 ID: " + id);
    itemRepository.deleteByPortfolioId(id); // 删除子项
    portfolioRepository.deleteById(id); // 删除组合
    logger.info("组合删除成功: " + id);
  }
}
